package com.demo.edit.util;

import com.alibaba.fastjson.JSON;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.*;

public class RedisManager {


    //timeout for jedis try to connect to redis server, not expire time! In milliseconds
    private static Integer TIME_OUT = 2000;

    private static JedisPool jedisPool = null;

    public RedisManager() {
    }

    public void init(String host, Integer port, Integer timeOut, String password) {
        jedisPool = new JedisPool(new JedisPoolConfig(), host, port, timeOut, password);
    }

    /**
     * get value from redis
     *
     * @param key
     * @return
     */
    public String get(String key) {
        String value = null;
        Jedis jedis = jedisPool.getResource();
        try {
            value = jedis.get(key);
        } catch (Exception e) {
            return null;
        } finally {
            jedis.close();
        }
        return value;
    }

    public <T> List<T> getAll(String tableName, Class<T> clazz) {
        Jedis jedis = jedisPool.getResource();
        Set<String> keys = jedis.keys(tableName + "*");
        Iterator<String> iterator = keys.iterator();
        List<T> list = new ArrayList<T>();
        while (iterator.hasNext()) {
            String next = iterator.next();
            String s = jedis.get(next);
            T t = JSON.parseObject(s, clazz);
            list.add(t);
        }
        jedis.close();
        return list;
    }

    public Boolean setAll(String tableName, String id, String key, List<Map<String, Object>> list) {
        Jedis jedis = jedisPool.getResource();
        try {
            list.forEach(item -> {
                Object o = item.get(key);
                String s = JSON.toJSONString(item);
                jedis.set(tableName + ":" + id + ":" + o, s);
            });
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
        return true;
    }

    public Boolean setAll(String tableName, String key, List<Map<String, Object>> list) {
        return this.setAll(tableName, key, key, list);
    }

    /**
     * get value from redis
     *
     * @param key
     * @return
     */
    public <T> T get(String key, Class<T> clazz) {
        String s = this.get(key);
        if (s == null) {
            return null;
        }
        return JSON.parseObject(s, clazz);
    }


    /**
     * set
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean set(String key, Object value) {
        String s = JSON.toJSONString(value);
        return this.set(key, s, null);
    }

    /**
     * set
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean set(String key, Object value, Integer expire) {
        String s = JSON.toJSONString(value);
        return this.set(key, s, expire);
    }

    /**
     * set
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean set(String key, String value) {
        return this.set(key, value, null);
    }

    /**
     * set
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean set(String key, String value, Integer expire) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.set(key, value);
            if (expire != null) {
                jedis.expire(key, expire);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            jedis.close();
        }
        return true;
    }

    /**
     * del
     *
     * @param key
     */
    public Boolean delete(String key) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.del(key);
        } catch (Exception e) {
            return false;
        } finally {
            jedis.close();
        }
        return true;
    }

    /**
     * del
     *
     * @param tableName
     */
    public Boolean deleteAllTable(String tableName) {
        Jedis jedis = jedisPool.getResource();
        try {
            Set<String> keys = jedis.keys(tableName + "*");
            for (String key : keys) {
                jedis.del(key);
            }
        } catch (Exception e) {
            return false;
        } finally {
            jedis.close();
        }
        return true;
    }

    /**
     * flush
     */
    public void flushDB() {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.flushDB();
        } finally {
            jedis.close();
        }
    }

    /**
     * size
     */
    public Long dbSize() {
        Long dbSize = 0L;
        Jedis jedis = jedisPool.getResource();
        try {
            dbSize = jedis.dbSize();
        } finally {
            jedis.close();
        }
        return dbSize;
    }

    /**
     * keys
     *
     * @param pattern
     * @return
     */
    public Set<String> keys(String pattern) {
        Set<byte[]> keys = null;
        Jedis jedis = jedisPool.getResource();
        try {
            return jedis.keys(pattern);
        } catch (Exception e) {
            return null;
        } finally {
            jedis.close();
        }
    }


    public void expire(String key, Integer expire) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.expire("key", expire);
        } catch (Exception e) {
        } finally {
            jedis.close();
        }
    }

    public Long getNextVal(String key) {
        Jedis jedis = jedisPool.getResource();
        try {
            Long incr = jedis.incr(key);
            if (incr == 1l) {
                jedis.expire(key, 365 * 24 * 60 * 60);
            }
            return incr;
        } catch (Exception e) {
            return null;
        } finally {
            jedis.close();
        }
    }


}